/*
 * symedge.hpp
 *
 *  Created on: 16/11/2011
 *      Author: Aeradon
 */

#ifndef SYMEDGE_HPP_
#define SYMEDGE_HPP_

#include <list>

#include "vertex.hpp"
#include "edge.hpp"
#include "face.hpp"
#include "constraint.hpp"
#include "point.hpp"

class Face;
class Constraint;
class Vertex;
class Edge;

class SymEdge
{
	typedef Vertex     	V;
	typedef Edge       	E;
	typedef SymEdge    	S;
	typedef Face	   	F;
	typedef float      	T;
	typedef Constraint 	C;
	typedef Point<T>	P;

public:
	SymEdge(V* v, E* e);

	void resetSymEdge(V* v, E* e);

	virtual ~SymEdge();

    /*! Returns the next symedge adjacent to the same face. */
	SymEdge*  nxt() const { return next; }

    /*! Returns the prior symedge adjacent to the same face. */
	SymEdge*  pri() const { return rotate->sym(); }

    /*! Returns the next symedge adjacent to the same vertex. */
	SymEdge*  rot() const { return rotate; }

    /*! Returns the prior symedge adjacent to the same vertex. */
	SymEdge*  ret() const { return symEdge->nxt(); }

    /*! Returns the symmetrical symedge, sharing the same edge. */
	SymEdge*  sym() const { return symEdge; }

    /*! Returns the element attached to the incident vertex. */
	Vertex*   vtx() const { return vertex; }

	/*! Returns the element attached to the incident vertex. */
	Vertex*   dst() const { return symEdge->vtx(); }

    /*! Returns the element attached to the incident edge. */
	Edge*     edg() const { return edge; }

    /*! Returns the element attached to the incident face. */
	Face*     fac() const { return face; }

	/*! Returns the element attached to the incident face. */
	Point<T>& nor() { return normal; }

	// Set everything
	void setNxt(SymEdge* next) { this->next = next; }

	void setRot(SymEdge* rotate) { this->rotate = rotate; }

	void setSym(SymEdge* symEdge) { this->symEdge = symEdge; }

	void setVtx(Vertex* vertex) { this->vertex = vertex; }

	void setEdg(Edge* edge) { this->edge = edge; }

	void setFac(Face* face) { this->face = face; }

	void setNor(T x, T y) {normal.x = x; normal.y = y;}

	// Constraint Operations
	void setConstrained(const std::list<C*>& l_c);
	void setConstrained(C* c);
	inline const std::list<C*>& getConstraints() const { return l_constraint; }
	void removeConstraint(C* c);
	bool hasConstraint(C* c);

public:
	bool isBoundary;
	bool isConstrained;

	unsigned int vecIndex;
	unsigned int mark;

private :
	V*	vertex;
	E*  edge;
	F*  face;
	P	normal;

	SymEdge* next;
	SymEdge* rotate;
	SymEdge* symEdge;

	std::list<C*> l_constraint;

};

#endif /* SYMEDGE_HPP_ */
